<template>
  <div class="my-aside">
    <el-row class="operating">
      <el-col :span="16" class="select-pro">
        <el-select v-model="data.selectedProject" filterable placeholder="请选择项目" popper-class="project-item" @change="changeProject">
          <el-option v-for="(item, index) in data.projects" :key="index" :label="item" :value="item">
          </el-option>
        </el-select>
      </el-col>
      <el-col :span="8" class="operating-items">
        <div class="item">
          <i class="el-icon-plus add-icon"></i>
          <span class="select-items">操作选项</span>
        </div>
        <ul class="items">
          <li @click="addProject">添加项目</li>
          <li @click="updateProject">修改项目</li>
          <li @click="deleteProject" v-if="whetherShowDelBtn">删除项目</li>
          <li @click="copyProject">复制所选项目</li>
          <li @click="generateProCode">获取项目代号</li>
          <li @click="generateTestData">生成测试数据</li>

        </ul>
      </el-col>
    </el-row>
    <el-row class="pwd-item">
      <el-col :span="10" class="enter-pwd">
        <el-input v-model="password" class="pwd" placeholder="输入密码进行操作"></el-input>
      </el-col>
      <el-col :span="8" :offset="6">
        <el-button type="primary" @click="addRootNode">添加树节点</el-button>
      </el-col>
    </el-row>

    <el-row class="tree-content">
      <el-tree :data="data.currentTreesData" node-key="id" :expand-on-click-node="false" :highlight-current="true" :default-expanded-keys="defaultExpandNodes" :props="{label: 'name'}" empty-text="暂无数据,请添加节点数据!">
        <span class="custom-tree-node" slot-scope="{ node, data }" @mouseenter="changeHoverSatus(true,data)" @mouseleave="leaveHover(false,data)">
          <span @click="loadNodeData(data)" @mouseenter="changeHoverSatus(true,data)" @mouseleave="leaveHover(false,data)">{{ node.label}}</span>
          <span v-show="data.isHover" @mouseenter="clearTimer()" @mouseleave="leaveHover(false,data)">
            <el-button type="text" size="medium" @click="lockNode(data)">
              <i class="iconfont lock-node">&#xe684;</i>
            </el-button>
            <el-button type="text" size="medium" @click="() => append(data)">
              <i class="el-icon-circle-plus-outline add-node"></i>
            </el-button>
            <el-button type="text" size="medium" @click="() => updateName(data)">
              <i class="el-icon-edit update-node"></i>
            </el-button>
            <el-button type="text" size="medium" @click="() => remove(node, data)">
              <i class="el-icon-delete del-node"></i>
            </el-button>
          </span>
          <el-button v-show="data.isLock && !data.isHover" type="text" size="medium">
            <i class="iconfont">&#xe684;</i>
          </el-button>
        </span>
      </el-tree>
    </el-row>
  </div>
</template>

<script>
import { request } from "@/js/_x/utils/request";
import { mapMutations } from "vuex";

export default {
  name: "myAside",
  computed: {
    pwdValid () {
      return !!this.password
    },
    password: {
      get () {
        return this.$store.state.aside.password
      },
      set (value) {
        this.changePwd(value)
      }
    }
  },
  data () {
    return {
      isExportProject: true,
      // 弹框自动消失时间
      duration: 6000,
      whetherShowDelBtn: process.env.NODE_ENV === "development",
      timer: null,
      defaultExpandNodes: [],
      data: {
        /*  */
        password: this.$store.state.aside.password,
        projects: [],
        /* 选中的项目 */
        selectedProject: "",
        // 选中的节点
        selectedNode: null,
        currentTreesData: []
      }
    };
  },
  methods: {
    ...mapMutations("aside", {
      changePro: "changeProject",
      changeIntf: "changeIntf",
      changePwd: "changePwd",
      changeWhetherLock: "changeWhetherLock"
    }),
    /* 获取所有项目-列表数据 */
    getProjects () {
      this.data.projects = [];
      request("api/interface/project/get_projects", {}, resp => {
        // console.log(resp);
        if (resp.result && resp.data && resp.data.length > 0) {
          this.data.projects = resp.data;
          if (!this.data.selectedProject) {
            this.data.selectedProject = this.data.projects[0];
          }
          this.changeProject();
        }
      }).catch(error => {
        console.log(error);
      });
    },
    /* 下拉列表change事件 */
    changeProject () {
      /* 保存选中的项目 */
      this.changePro(this.data.selectedProject);
      this.getProjectInfo();
    },
    /* 获取项目的详细接口数据 */
    getProjectInfo () {
      request(
        "api/interface/tree/get_tree",
        { projectName: this.data.selectedProject },
        resp => {
          if (resp.result && resp.data) {
            let data = [];
            for (let prop in resp.data) {
              data.push(...resp.data[prop]);
            }
            /* 转化成父子关系数据结构 */
            this.data.currentTreesData = this.changeDataToTree(data);
            // console.log(this.data.currentTreesData);
          } else {
            this.data.currentTreesData = [];
          }
        }
      ).catch(error => {
        this.data.currentTreesData = [];
        console.log(error);
      });
    },
    showPrompt ({ message, title, defaultValue }, success, cancel) {
      this.$prompt(message, title, {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        inputValue: defaultValue,
        center: true
      })
        .then(({ value }) => {
          if (typeof success === "function") {
            success(value);
          }
        })
        .catch(error => {
          if (typeof cancel === "function") {
            cancel(error);
          }
        });
    },
    addProject () {
      this.showPrompt({ message: "请输入项目名：", title: "新增项目" }, value => {
        request(
          "api/interface/project/add_project",
          { projectName: value },
          resp => {
            console.log(resp);
            if (resp.result) {
              this.$message({ message: "添加成功!", type: "success" });
              /* 重新获取下拉列表数据 */
              this.getProjects();
            } else {
              this.$message({
                message: "添加失败! " + resp.message,
                type: "error"
              });
            }
          }
        ).catch(error => {
          console.log(error);
          this.$message({ message: "添加失败!", type: "error" });
        });
      });
    },
    deleteProject () {
      this.$confirm("确认删除该项目?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        request(
          "api/interface/project/delete_project",
          { projectName: this.data.selectedProject },
          resp => {
            if (resp.result) {
              this.$message({ message: "删除成功!", type: "success" });
              /* 重新获取下拉列表数据 */
              this.data.selectedProject = ""
              this.getProjects();
            } else {
              this.$message({
                message: "删除失败! " + resp.message,
                type: "error"
              });
            }
          }
        ).catch(error => {
          console.log(error);
          this.$message({ message: "后台异常,删除失败!", type: "error" });
        });
      })
    },
    // 生成项目代号
    generateProCode () {
      console.log(window.intf_project_name)
      request(
        "api/interface/project/get_project_code",
        { projectName: this.data.selectedProject },
        resp => {
          if (resp.result) {
            this.$notify({
              title: '获取成功',
              message: `项目代号：${resp.data}`,
              duration: this.duration,
              position: "top-left",
              type: 'success'
            });
          } else {
            this.$notify({
              title: '获取失败',
              message: `${resp.message}`,
              duration: this.duration,
              position: "top-left",
              type: 'error'
            });
          }
        }
      ).catch(error => {
        console.log(error);
        this.$notify({
          title: '获取失败',
          message: `后台异常!`,
          duration: this.duration,
          position: "top-left",
          type: 'error'
        });
      });
    },
    // 生成测试数据
    generateTestData () {
      request(
        "api/interface/project/generate_test_data",
        { projectName: this.data.selectedProject },
        resp => {
          if (resp.result) {
            this.$message({
              message: `生成测试数据成功!可以进行接口访问测试`,
              type: 'success'
            });
          } else {
            this.$message({
              message: `生成测试数据失败!${resp.message}`,
              type: 'error'
            });
          }
        }
      ).catch(error => {
        console.log(error);
        this.$message({
          message: `后台异常,生成测试数据失败!`,
          type: 'error'
        });
      });
    },
    updateProject () {
      this.showPrompt({ message: "新的项目名：", title: "修改项目名称", defaultValue: this.data.selectedProject }, value => {
        let oldName = this.data.selectedProject;
        request(
          "api/interface/project/update_project",
          { newProjectName: value, oldProjectName: oldName },
          resp => {
            console.log(resp);
            if (resp.result) {
              this.$message({ message: "修改项目名称成功!", type: "success" });
              /* 设置显示信息 */
              this.data.selectedProject = value;
              // this.data.projects[this.data.projects.indexOf(oldName)] = value;
              this.getProjects();
            } else {
              this.$message({
                message: "修改项目名称失败! " + resp.message,
                type: "error"
              });
            }
          }
        ).catch(error => {
          console.log(error);
          this.$message({ message: "修改失败!", type: "error" });
        });
      });
    },
    copyProject () {
      this.showPrompt({ message: "请输入新的项目名：", title: "复制项目", defaultValue: this.data.selectedProject }, value => {
        let params = {
          newProjectName: value,
          oldProjectName: this.data.selectedProject
        };
        request("api/interface/project/add_project_by_old", params, resp => {
          if (resp.result) {
            this.$message({ message: "复制成功!", type: "success" });
            /* 重新获取下拉列表数据 */
            this.getProjects();
          } else {
            this.$message.error(`复制失败! ${resp.message}`);
          }
        }).catch(error => {
          console.log(error)
          this.$message.error(`后台异常,复制失败!`);
        });
      });
    },
    /* 添加根节点 */
    addRootNode () {
      /* api/interface/tree/add_parent_node */
      this.showPrompt({ message: "输入根节点名称:  ", title: "添加根节点" }, value => {
        const params = {
          projectName: this.data.selectedProject,
          parentNodeName: value,
          password: this.password,
          id: ""
        };
        request("api/interface/tree/add_parent_node", params, resp => {
          // console.log(resp);
          if (resp.result) {
            this.$message({ message: "添加成功!", type: "success" });
            /* 重新获取下拉列表数据 */
            this.getProjects();
          } else {
            this.$message({
              message: "添加失败! " + resp.message,
              type: "error"
            });
          }
        }).catch(error => {
          console.log(error);
          this.$message({ message: "添加失败!", type: "error" });
        });
      });
    },
    /* 将后台的数据转化成父子结构数据返回 */
    changeDataToTree (data) {
      let map = new Map();
      data.forEach(item => {
        map.set(item.id, item);
      });
      let tree = [];
      data.forEach(item => {
        let parent = map.get(item.pId);
        if (parent) {
          (parent.children || (parent.children = [])).push(item);
        } else {
          /* 说明是根节点，直接加入数组中 */
          tree.push(item);
        }
      });
      /* 加上是否是叶子节点标记 */
      this.lockTreeNode(tree);
      return tree;
    },
    /* 标记哪些是叶子节点 children: 子节点字段，可以自定义 */
    lockTreeNode (data, children) {
      children = children || "children"
      data.forEach(item => {
        if (item[children]) {
          item["isLeaf"] = false
          this.lockTreeNode(item[children], children)
        } else {
          /* //不存在，叶子节点 */
          item["isLeaf"] = true
        }
      })
    },
    /* 节点加锁操作 */
    lockNode (data) {
      let info = data.isLock ? "解锁" : "加锁";
      /* 验证是否填写密码 */
      if (!this.pwdValid) {
        this.$message({
          message: `请输入密码在进行${info}操作!`,
          type: "warning"
        });
        return;
      }
      let params = {
        projectName: this.data.selectedProject,
        password: this.password,
        id: data.id
      };
      let url = data.isLock
        ? "api/interface/tree/unlock"
        : "api/interface/tree/add_lock";
      request(url, params, resp => {
        if (resp.result) {
          this.$message.success(`${info}成功!`);
          /* 设置当前数据为加锁或解锁状态数据 */
          this.defaultExpandNodes = [data.id];
          this.getProjectInfo();
          // 通知编辑页面这里进行加锁操作了 但是如果解锁是别的节点就不需要刷新状态
          if (data.id === this.data.selectedNode.id) {
            this.changeWhetherLock(new Date().getTime())
          }
        } else {
          this.$message.error(`${info}失败!${resp.message}`);
        }
        console.log(resp);
      }).catch(error => {
        console.log(error);
        this.$message.error(`后台异常,${info}失败`);
      });
    },
    append (data, flag) {
      /* flag=true，就是修改节点名称 */
      if (!data.isLock) {
        this.$message.warning("请先加锁!")
        return
      }
      let url = flag
        ? "api/interface/tree/update_node"
        : "api/interface/tree/add_node";
      let expandId = flag ? data.pId : data.id;
      let info = flag ? "修改" : "添加";
      let defaultValue = flag ? data.name : ""
      if (!this.pwdValid) {
        this.$message.warning(`请输入密码,在${info}节点!`);
        return;
      }
      this.showPrompt({ message: "输入节点名称：", title: "", defaultValue }, value => {
        let params = {
          projectName: this.data.selectedProject,
          nodeName: value,
          password: this.password,
          id: data.id
        };
        request(url, params, resp => {
          if (resp.result) {
            this.$message.success(`${info}成功!`);
            /* 设置页面数据显示 */
            this.defaultExpandNodes = [expandId];
            this.getProjectInfo();
          } else {
            this.$message.error(`${info}节点失败!原因: ${resp.message}`);
          }
        }).catch(error => {
          console.log(error);
          this.$message.error(`后台异常,${info}节点失败!`);
        });
      });
    },
    /* //移除一个节点 */
    remove (node, data) {
      if (!data.isLock) {
        this.$message.warning("请先加锁!")
        return
      }
      this.$confirm("确认删除节点?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        let params = {
          projectName: this.data.selectedProject,
          password: this.password,
          id: data.id
        };
        request("api/interface/tree/delete_node", params, resp => {
          if (resp.result) {
            this.$message.success("删除成功!");
            /* 每次展开删除节点的父节点 */
            this.defaultExpandNodes = [data.pId];
            this.getProjectInfo();
          } else {
            this.$message.error(`删除失败!原因: ${resp.message}`);
          }
        }).catch(error => {
          console.log(error);
          this.$message.error(`后台异常,删除失败!`);
        });
      });
    },
    updateName (data) {
      this.append(data, true);
    },
    showLock (data) {
      return data.isLock || data.isHover;
    },
    // hover节点时显示隐藏图标
    changeHoverSatus (status, data) {
      this.$set(data, "isHover", status);
    },
    leaveHover (status, data) {
      this.timer = setTimeout(() => {
        this.$set(data, "isHover", status);
      }, this.delayTime);
    },
    clearTimer () {
      if (this.timer) {
        clearTimeout(this.timer);
      }
    },
    /*  加载节点数据的方法集 */
    loadNodeData (data) {
      this.data.selectedNode = data
      this.changeIntf(data)
    }
  },
  mounted () {
    /* 1 获取项目列表数据 */
    this.getProjects();
  }
};
</script>

<style lang="scss" scoped>
@import "~@/assets/styles/mixin.scss";
@import "~@/assets/styles/home/aside.scss";
</style>
